package relop;

import externalSort.SortMergeJoin;

/**
 * The selection operator specifies which tuples to retain under a condition; in
 * Minibase, this condition is simply a set of independent predicates logically
 * connected by OR operators.
 */
public class Selection extends Iterator {
	Predicate[] mypred;
	FileScan myscan;
	Tuple cur_sat;
  /**
   * Constructs a selection, given the underlying iterator and predicates.
   */
  public Selection(FileScan scan, Predicate[] preds) {
	  
	  myscan = scan;
	  mypred = preds;
	  this.schema = scan.schema;
  }

  public Selection(SortMergeJoin join2, Predicate predicate) {
	// TODO Auto-generated constructor stub
	  System.out.println("Selection for SortMergeJoin");
	  myscan = join2.getFileScan();
	  mypred = new Predicate[1]; 
	  mypred[0] = predicate;
	  this.schema = myscan.schema;
  }

/**
   * Gives a one-line explanation of the iterator, repeats the call on any
   * child iterators, and increases the indent depth along the way.
   */
  public void explain(int depth) {
    //throw new UnsupportedOperationException("Not implemented");
	  System.out.println("This Selection Iterator receive the type of FileScan and all the predicates.");
	  System.out.println("Then use the predicates to select all satisfied tuples.");

  }

  /**
   * Restarts the iterator, i.e. as if it were just constructed.
   */
  public void restart() {
   // throw new UnsupportedOperationException("Not implemented");
	  myscan.restart();
  }

  /**
   * Returns true if the iterator is open; false otherwise.
   */
  public boolean isOpen() {
   // throw new UnsupportedOperationException("Not implemented");
	  if(myscan.isOpen()) 
		  return true;
	  else 
		  return false;
  }

  /**
   * Closes the iterator, releasing any resources (i.e. pinned pages).
   */
  public void close() {
   // throw new UnsupportedOperationException("Not implemented");
	  myscan.close();
  }

  /**
   * Returns true if there are more satisfied tuples, false otherwise.
   */
  /**
   * We need to find the next satisfied tuple, if there is some tuple, save it and return true.
   * Else return false say there is no more satisfied tuple in this file.
   */
  public boolean hasNext() {
   // throw new UnsupportedOperationException("Not implemented");
	  if(cur_sat!=null)
		  return true;
	  
	  if(myscan.isOpen()){
		  while(myscan.hasNext()){
			  Tuple thistuple = myscan.getNext();
			  boolean success = true;
			  for(int i=0; i<mypred.length; i++){
				  Predicate cur_p = mypred[i];
				  boolean thisSuccess = cur_p.evaluate(thistuple);
//				  thistuple.print();
				  if(thisSuccess == false)
					  success = false;
//				  cur_p.print();
//				  System.out.println("isSuccess: "+success);
				 
			  }
			  if(success==true){
				  cur_sat = thistuple;
				  return true;
			  }
			  else
				  continue;
		  }  
	  }
	  return false;	  
	  
  }

  /**
   * Gets the next tuple in the iteration.
   * 
   * @throws IllegalStateException if no more tuples
   */
  public Tuple getNext() {
   // throw new UnsupportedOperationException("Not implemented");
	  if(cur_sat!=null){
		  Tuple temp = cur_sat;
		  cur_sat = null;
		  return temp;
	  }
	  
	  if(myscan.isOpen()){
		  while(myscan.hasNext()){
			  Tuple thistuple = myscan.getNext();
			  for(int i=0; i<mypred.length; i++){
				  Predicate cur_p = mypred[i];
				  boolean success = cur_p.evaluate(thistuple);
				  if(success==true){
					  //cur_sat = thistuple;
					  return thistuple;
				  }
				  else
					  continue;
			  }
		  }  
	  }
	  return null;
	  
  }

} // public class Selection extends Iterator
